<?php
declare (strict_types=1);

namespace app\middleware;

use app\Request;
use app\services\UserAuthServices;
use think\facade\Env;
use utils\Define;

class AuthToken
{
    protected $data; // 请求数据


    /**
     * Check constructor.
     */
    public function __construct()
    {
        header("Access-Control-Allow-Origin:*");
        header('Access-Control-Allow-Methods:POST,GET');
        header('Access-Control-Allow-Headers:x-requested-with, content-type');
    }

    /**
     * 处理请求
     * @param Request $request
     * @param \Closure $next
     * @return mixed
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function handle(Request $request, \Closure $next)
    {
        try {
            $url = mb_substr($request->url(), 1);
            $data = $request->param(); // 请求参数
            if (!in_array($url, Define::NotSignUrl)) {
                $token = trim($request->header('token', ''));
                try {
                    $service = app()->make(UserAuthServices::class);
                    $user_info = $service->parseToken($token);
                } catch (\Exception $e) {
                    return app('json')->json_error($e->getMessage(), $e->getCode());
                }
                $request->user_id = is_null($user_info) ? 0 : $user_info['id']; // 用户uid
                $data['user_id'] = $request->user_id;
                $request->user = $user_info ?: null; // 用户信息
                $sign = trim($request->header('sign', '')); // 接口签名

//                if (empty($sign)) {
//                    return app('json')->json_error('签名不存在');
//                }
//                if ($this->ApiSign($user_info['id'], $data) != $sign) {
//                    return app('json')->json_error('签名不正确');
//                }
            }
            $request->data = $data;
        } catch (\Throwable $e) {
            return app('json')->json_error($e->getMessage(), 401);
        }
        return $next($request);
    }

    /**
     * 获取接口签名
     * @param int $uid
     * @param array $params
     * @return string
     */
    protected function ApiSign(int $uid, array $params): string
    {
        unset($params['sign']);

        $params['uid'] = $uid;

        //签名步骤一：按字典序排序数组参数
        ksort($params);
        $string = $this->toUrlParams($params);
        //签名步骤二：在string后加入KEY
        $app_key = env('app.app_key');
        $string = trim($string . "&key=" . $app_key);
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 将参数拼接为url: key=value&key=value
     * @param  $params
     * @return string
     */
    protected function toUrlParams($params)
    {
        $string = '';
        if (!empty($params)) {
            $array = array();
            foreach ($params as $key => $value) {
                if (is_array($value))
                    $value = json_encode($value);
                if (is_string($value))
                    $value = htmlspecialchars_decode($value);
                $array[] = $key . '=' . $value;
            }
            $string = implode("&", $array);
        }
        return $string;
    }
}
